Lab 06 - Wprowadzenie do ROS 2 - struktura środowiska i podstawowe koncepty

Wprowadzenie do ROS 2 - struktura środowiska i podstawowe koncepty

Robot Operating System

Robot Operating System (ROS) to zestaw bibliotek programistycznych i narzędzi do budowania aplikacji robotycznych. ROS oferuje narzędzia open-source od sterowników sensorów i robotów, po zaawansowane algorytmy. Od końcówki roku 2017 istnieje pierwsza dystrybucja ROS'a 2, Ardent Apalone, która znacznie poszerza funkcjonalności ROS'a 1 (opisane tutaj). Obecnie w ramach laboratorium wykorzystywana jest najnowsza stabilna wersja - Humble Hawksbill. Pomimio tej zmiany, kluczowe koncepty pozostały takie same:

🐢 przetwarzanie oparte o niezależne moduły (koncepcja grafów - węzły, ang. nodes),

🐢 komunikacja poprzez publikowanie i subskrypcję (ang. publisher/subscriber),

🐢 komunikacja z informacją zwrotną poprzez serwisy lub akcje (ang. services, actions),

🐢 neutralność językowa (istnieje możliwość integracji z dowolnym językiem programowania, ang. ROS client library).

ROS 1 dedykowany pod zaawansowane projekty badawcze nie mógł zostać wdrożony 1:1 do zastosowań przemysłowych. Ograniczały go słabości związane z bezpieczeństwem dostępu do wiadomości oraz brak dostosowania do wymagań systemów czasu rzeczywistego. Druga generacja, ROS 2, została przeprojektowana, aby sprostać tym wyzwaniom. Różnice pomiędzy wersjami zostały opisane w artykule.

Podstawowe pojęcia

Środowisko (ang. workspace)

Środowisko ROS'a to miejsce, w którym przechowywane są paczki np. dla danego robota. Na jednym komputerze może istnieć wiele różnych środowisk (np. ros2_robotA_ws, ros2_robotB_ws).

Przykładowa struktura środowiska:

ros2_ws
├── build - zawiera pliki służące do procesu budowania, dzięki nim ponowne budowanie może uwzględnić tylko nowe zmiany
├── install - miejsce, w którym instalowane są paczki
├── log - zawiera logi procesu budowania
└── src - miejsce pracy ROS dewelopera zawierające paczki

Budowanie środowiska ROS 2 odbywa się z wykorzystaniem colcon, poniższą komendą:

colcon build

Możliwe jest zbudowanie pojedynczej paczki:

colcon build --packages-select package_name

Pierwszym krokiem przed rozpoczęciem pracy ze zbudowanym środowiskiem ROS'a jest ustawienie zmiennych środowiskowych (source'owanie), dzięki czemu możemy uzyskać dostęp do paczek w danym terminalu.

W katalogu ~/ros2_ws wywołaj komendę:

source install/setup.bash

Za każdym razem, gdy otwierasz okno terminala i zamierzasz pracować w danym środowisku, wywołaj powyższą komendę w odpowiednim katalogu.

Powinna ona zostać wywołana w katalogu głównym środowiska ROS 2 (np. ~/ros2_ws).

Paczka

Paczkę to miejsce, w którym przechowywane są węzły. Służy do organizacji kodu tak, aby zapewnić modułowość oprogramowania.

Przykładowa struktura paczki (Python):

my_package/
      my_package - katalog zawierający węzły
      setup.py - zawiera instrukcje dotyczące instalacji paczki
      setup.cfg - przechowuje informacje o plikach wykonywalnych
      package.xml - zawiera informację o paczce oraz jej zależności
      resource/my_package - katalog wymagany, aby zlokalizować paczkę
      test - zawiera skrypty do automatycznego testowania

Organizowanie paczek odbywa się poprzez wykorzystanie ament, ewolucji catkin znanej z ROS 1. Dzięki temu narzędziu paczki mają usystematyzowaną strukturę.

Tworzenie paczki (C++):

ros2 pkg create --build-type ament_cmake package_name

Tworzenie paczki (Python):

ros2 pkg create --build-type ament_python package_name

Możliwe jest wskazanie zależności z argumentem --dependencies oraz jednoczesne utworzenie węzła poprzez dodatkowy argument --node-name.

Zarządzanie zależnościami paczki

Narzędziem istotnie usprawniającym pracę dewelopera ROS jest rosdep. Pozwala ono na automatyczną instalację zależności (paczek, bibliotek) wszystkich paczek w danym środowisku. Dzięki temu, że zależności są definiowane w pliku package.xml nie ma konieczności ręcznej ich instalacji.

Wiele gotowych paczek znajduje się w repozytorium ROS - rosdistro, każdy użytkownik ma możliwość dodania do niego swojej paczki poprzez pull request. Informacja o tym jak dodać paczkę, która jeszcze nie znajduje się na liście jest tutaj.

Aby wykorzystać rosdep wywołaj poniższe komendy wewnątrz katalogu ~/ros2_ws:

sudo rosdep init
rosdep update
rosdep install --from-paths src -y --ignore-src --rosdistro humble

Te polecenia zainicjują rosdep, a następnie zaktualizują lokalne indeksy z bazy paczek rosdistro. Ostatnia komendy dokonuje instalacji zależności. Argument --from-paths src mówi o tym, aby szukać plików package.xml wewnątrz katalogu src, -y powoduje automatyczne akceptowanie komunikatów w konsoli, a --ignore-src pomija w instalacji paczki znajdujące się w katalogu src (ponieważ one zostaną przez nas zbudowane).

Węzeł

Węzeł reprezentuje pojedynczy proces w ROS'ie. Węzły mogą publikować lub subskrybować tematy, udostępniać usługi i akcje lub z nich korzystać.

Uruchamianie węzłów odbywa się poprzez komendę:

ros2 run package_name node_name

Aby uzyskać aktualną listę węzłów:

ros2 node list

Uzyskanie informacji o węźle:

ros2 node info <node_name>

Koncepcja grafów (ROS 2 graph)

Graf ROS (ang. ROS graph) to sieć węzłów przetwarzających dane. Obejmuje wszystkie węzły i połączenia komunikacyjne między nimi. Graf ROS'a zawiera:

🐢 węzły - procesy wymieniające wiadomości

🐢 wiadomości - typy wymienianych danych

🐢 tematy - kanał komunikacji pomiędzy węzłami

🐢 odkrywanie - automatyczny proces nawiązywania połączenia pomiędzy węzłami

Narzędziem, które umożliwia podgląd i wizualizację aktualnego stanu grafu jest:

rqt_graph

Przykładowa wizualizacja grafu:

Możliwe jest grupowanie węzłów umożliwiając ich zbiorcze uruchamianie. Służą do tego pliki launch. Wywołanie istniejącego pliku launch odbywa się poprzez polecenie:

ros2 launch package_name launch_name

W ROS 2 pliku launch mogą przyjmować jedno z trzech rozszerzeń, .xml, .py lub .yaml. Rozszerzenie .py jest rekomendowane ze względu na elastyczność tego języka. Więcej informacji na ten temat znajduje się w odnośniku do plików launch.

Temat

Temat to unikalna nazwa, dzięki której węzły mogą nawiązywać połączenia oraz się komunikować. Temat powstaje w momencie, gdy węzeł rozpoczyna publikację określonego typu wiadomości.

Pojedynczy węzeł może publikować wiadomości na wielu tematach oraz subskrybować wiadomości z wielu tematów.

Podgląd aktualnej listy tematów odbywa się z wykorzystaniem komendy:

ros2 topic list

Lista tematów wraz z związanymi z nimi typami wiadomości:

ros2 topic list -t

Odczyt wiadomości z tematu:

ros2 topic echo topic_name

Pojedynczy temat może mieć wielu publikujących jak i subskrybentów. Informację o nich, a także o typie wymienianej wiadomości można sprawdzić komendą:

ros2 topic info topic_name

Możliwe jest również publikowanie wiadomości na danym temacie z poziomu terminala:

ros2 topic pub topic_name message_type 'message_data'

Example:
ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"

Aby opublikować wiadomość raz, można użyć argumentu --once.

Odczyt częstliwości z jaką publikowane są dane na temacie:

ros2 topic hz topic_name

Wiadomość

Wiadomość jest elementem komunikacji pomiędzy węzłami. Może zawierać różnego rodzaju informację (np. położenie, orientację, obraz z kamery). Przykładowe domyślne typy wiadomości:

🐢 geometry_msgs/msg/Twist

🐢 sensor_msgs/msg/Image

🐢 std_msgs/msg/Header

Aby uzyskać informacji o wiadomości:

ros2 interface show message_type

Wizualizacja wiadomości

RViz to graficzny interfejs, który umożliwia wyświetlanie informacji z tematów z wykorzystaniem wbudowanych pluginów. Pozwala na spojrzenie na świat oczami robota lub sensora. Dla ROS 2, RViz uruchamiamy poleceniem:

rviz2

Symulacja dynamiczna

Gazebo to środowisko symulacyjne, które umożliwia tworzenie otoczenia pracy dla robota i symulację jego interakcji z obiektami. Gazebo uruchamiamy poleceniem:

gazebo

ROS w Dockerze

Na początek warto zbudować własny, rozszerzony obraz na podstawie oficjalnego za pomocą następującego Dockerfile:

FROM ros:humble

RUN apt-get update && apt-get -y upgrade && apt-get -y install ros-humble-desktop

Budowanie można wykonać za pomocą polecenia:

docker build -t ros2_lab .

Kontener na podstawie oficjalnego obrazu można uruchomić poleceniem:

xhost +local:root && docker run -it \
    --env="DISPLAY" \
    --env="QT_X11_NO_MITSHM=1" \
    --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    -v ~/ros2:/root/ros2 \
    --net=host \
    --privileged \
    --name=ros2_lab \
    ros2_lab:latest

Tak przygotowany kontener będziemy mogli wykorzystywać wielokrotnie. W celu ponownego uruchomienia wystarczy wywołać polecenie:

docker start -i ros2_lab

Jeśli potrzebujemy dodatkowego terminala działającego "w kontenerze", możemy go otworzyć poleceniem:

docker exec -it ros2_lab bash

Praca z ROS'em 2 przy wielu komputerach w lokalnej sieci

Standardem używanym przez ROS 2 do komunikacji jest DDS. W DDS istnieje pojęcie "domen". Pozwalają one na logiczne rozdzielenie połączeń w obrębie sieci.

Węzły w tej samej domenie mogą swobodnie siebie wykrywać i wysyłać do siebie wiadomości, podczas gdy węzły znajdujące się w różnych domenach nie mogą. Wszystkie węzły ROS 2 domyślnie używają identyfikatora domeny 0. Aby uniknąć zakłóceń między różnymi grupami komputerów z systemem ROS 2 w tej samej sieci, dla każdej grupy należy ustawić inny identyfikator domeny. W obrębie laboratorium konieczne jest ustawienie osobnego unikalnego ID domeny dla każdego z komputerów. W tym celu, odczytaj numer z naklejki przyklejonej do monitora i podstaw go do poniższej komendy w miejscu NR_KOMPUTERA. Jeśli na Twoim komputerze nie ma naklejki, wybierz numer z przedziału 0-101 lub 215-232. Więcej informacji znajdziesz w poniższym odnośniku: About domain ID.

grep -q ^'export ROS_DOMAIN_ID=' ~/.bashrc || echo 'export ROS_DOMAIN_ID=NR_KOMPUTERA' >> ~/.bashrc

Powyższa komenda spowoduje, że w każdym oknie terminala ustawiany będzie wskazany identyfikator domeny. Dzięki temu węzły nie będą widoczne pomiędzy różnymi komputerami w tej samej sieci.

Zadania

  1. Dokonaj zmiany id domeny na unikalną. W tym celu odczytaj numer z naklejki przyklejonej do monitora (np. K006 - wybieramy tylko liczbę 6) i podstaw go do poniższej komendy w miejscu NR_KOMPUTERA. Jeśli na Twoim komputerze nie ma naklejki, wybierz numer z przedziału 0-101 lub 215-232.
grep -q ^'export ROS_DOMAIN_ID=' ~/.bashrc || echo 'export ROS_DOMAIN_ID=NR_KOMPUTERA' >> ~/.bashrc

💡Aby zaobserwować zmiany zamknij obecne okno terminala i uruchom nowe lub jeśli nie chcesz zamykać okna terminala, wpisz source ~/.bashrc.

  1. Zainstaluj i uruchom przykładowy węzeł. Pobierz paczkę usb_cam i umieść ją w katalogu src środowiska ROS 2. Wykorzystaj komendę git clone --branch ros2 https://github.com/ros-drivers/usb_cam.git.
  2. Paczka usb_cam definiuje zależność od innych paczek. Dokonaj automatycznej instalacji zależności z wykorzystaniem rosdep.
  3. Zbuduj środowisko ROS 2 poleceniem colcon build i dokonaj source'owania: source install/setup.bash.

💡Uwaga: w przypadku problemów z powyższą instalacją ze źródeł, istnieje druga możliwość zainstalowania paczki. Możesz dokonać instalacji systemowej poleceniem sudo apt-get install ros-humble-usb-cam. W tym przypadku paczka nie pojawi się w katalogu src lokalnego środowiska i nie będzie konieczności budowania tej paczki. Aby wczytać biblioteki zainstalowane w systemie wykorzystaj komendę: source /opt/ros/humble/setup.bash zamiast lokalnego odpowiednika.

  1. Uruchom węzeł zainstalowanej paczki poleceniem: ros2 run usb_cam usb_cam_node_exe

  2. W nowym oknie terminala (Ctrl + Shift + T), dokonaj następującej analizy:

    5.1. Wyświetl listę tematów.

    5.2. Wyświetl informację o temacie /image_raw.

    5.3. Wyświetl wiadomości z tematu /image_raw.

  3. Uruchom RViz poleceniem rviz2 i wyświetl obraz z kamery. W tym celu zlokalizuj przycisk "Add" -> "By topic" -> /image_raw -> Image.

  4. Wyświetl obraz z wykorzystaniem węzła image_view, dokonaj instalacji jeśli to będzie konieczne.

    sudo apt-get install ros-humble-image-view
    ros2 run image_view image_view --ros-args --remap /image:=/image_raw
  5. Uruchom rqt_graph. Następnie ponownie zasubkrybuj temat /image_raw i zaobserwuj zmiany w grafie.

  6. Zainstaluj i uruchom paczkę sensors_demos_gazebo do symulacji sensorów (instrukcja jest w pliku README paczki). Umieść ją w katalogu src środowiska ROS 2. Do uruchomienia wykorzystaj pliki launch.

    9.1. IMU

    IMU to układ elektroniczny wyposażony w jeden lub wiele trójosiowych żyroskopów i akcelerometrów. Możliwe jest również dołączenie magnetometru.

    Dokonaj symulacji urządzenia w Gazebo i zapoznaj się z publikowanym tematem. Wyświetl jego zawartość w terminalu.

    9.2. Kinect

    Kinect jest popularnie wykorzystywany w robotyce do lokalizowania robotów, wykrywania przeszkód i budowania modeli otoczenia. Sensor zwraca obraz RGB i obraz głębi.

    Dokonaj symulacji sensora w Gazebo i zapoznaj się z listą tematów. Wyświetl ich zawartość w terminalu i w RViz'ie.

    Zastanów się, dlaczego chmura punktów jest obrócona a obrazy nie nakładają się na siebie (w osi z).

    9.3. Hokuyo URG-04LX 2D laser scanner

    Skaner laserowy URG-04LX-UG01 ma zakres pomiarowy od 20 mm do 5600 mm z dokładnością co do 1 mm.

    Dodaj dowolne obiekty w zasięgu skaneru z interfejsu Gazebo lub przy pomocy menu wczytywania modeli.

    Zapoznaj się z listą tematów i wyświetl ich zawartość w terminalu i w RViz'ie.

Źródła i przydatne odnośniki

🐢 ROS 2 - developer guide

🐢 ROS 2 - documentation

🐢 ROS2 - design

🐢 ROS2 - instalacja - Desktop Install